﻿using System;

using Toenda.Foundation.Utility;
using Toenda.Foundation.Globalization;

namespace Toenda.Foundation {
	/// <summary>
	/// Implements a datetime helper class
	/// </summary>
	public static class DateTimeHelper {
		private static DateTime? _defaultDateTime;

		/// <summary>
		/// Gets the default date
		/// </summary>
		public static DateTime Default {
			get {
				if(_defaultDateTime != null) {
					return _defaultDateTime.Value;
				}
				else {
					_defaultDateTime = new DateTime(1, 1, 1, 0, 0, 0, 0);
					return _defaultDateTime.Value;
				}
			}
		}

		/// <summary>
		/// Create a new date
		/// </summary>
		/// <param name="year">The year of the new date time.</param>
		/// <param name="month">The month of the new date time.</param>
		/// <param name="day">The day of the new date time.</param>
		/// <returns>Returns a new datetime object.</returns>
		public static DateTime New(int year, int month, int day) {
			return Calendar.ParseDate(year, month, day);
		}

		/// <summary>
		/// Create a new date
		/// </summary>
		/// <param name="year">The year of the new date time.</param>
		/// <param name="month">The month of the new date time.</param>
		/// <param name="day">The day of the new date time.</param>
		/// <param name="hour">The hour of the new date time.</param>
		/// <param name="minute">The minute of the new date time.</param>
		/// <param name="second">The second of the new date time.</param>
		/// <returns>Returns a new datetime object.</returns>
		public static DateTime New(int year, int month, int day, int hour, int minute, int second) {
			return Calendar.ParseDate(year, month, day, hour, minute, second);
		}

		/// <summary>
		/// Create a new date from an in in format (yyyyMMdd)
		/// </summary>
		/// <param name="date">The datetime object as datetime number that should be parsed.</param>
		/// <returns>Returns a datetime object that is initialized by the parameter.</returns>
		public static DateTime ParseFromInt(int date) {
			return ParseByFormat(date.ToString(), "yyyyMMdd");
		}

		/// <summary>
		/// Parse a string by a format (yyyyMMdd)
		/// </summary>
		/// <param name="date">The datetime object as datetime string that should be parsed.</param>
		/// <returns>Returns a datetime object that is initialized by the parameter.</returns>
		public static DateTime ParseByFormat(string date) {
			return ParseByFormat(date, "yyyyMMdd");
		}

		/// <summary>
		/// Parse a string by a format
		/// </summary>
		/// <param name="date">The datetime object as datetime string that should be parsed.</param>
		/// <param name="format">The format of the datetime string.</param>
		/// <returns>Returns a datetime object that is initialized by the parameter.</returns>
		public static DateTime ParseByFormat(string date, string format) {
			string tmp = format.CleanFromCharacters("0123456789");
			string tmpDate = date.CleanFromCharacters(tmp);

			if(!tmpDate.IsNumeric()) {
				return DateTimeHelper.Default;
			}
			else {
				DateTimeProperties dtp = GetPropertiesByFormat(date, format);
				return Calendar.CorrectDate(dtp.Year, dtp.Month, dtp.Day);
			}
		}

		/// <summary>
		/// Get the propertie items of a string-formated datetime (default format: yyyyMMdd)
		/// </summary>
		/// <param name="date">The datetime object as datetime string that should be parsed to a datetime properties object.</param>
		/// <returns>Returs the datetime properties of this date string.</returns>
		public static DateTimeProperties GetPropertiesByDefaultFormat(string date) {
			return GetPropertiesByFormat(date, "yyyyMMdd");
		}

		/// <summary>
		/// Get the propertie items of a string-formated datetime
		/// </summary>
		/// <param name="date">The datetime object as datetime string that should be parsed to a datetime properties object.</param>
		/// <param name="format">The format of the datetime string.</param>
		/// <returns>Returs the datetime properties of this date string.</returns>
		public static DateTimeProperties GetPropertiesByFormat(string date, string format) {
			int DT_LENGTH = format.Length;

			if(date.Length < DT_LENGTH) {
				date = date.PadLeft(DT_LENGTH, '0');
			}

			if(date.Length > DT_LENGTH) {
				date = date.Substring(0, DT_LENGTH);
			}

			switch(format) {
				case "MM/dd/yyyy":
				case "MM-dd-yyyy":
					return new DateTimeProperties() {
						Year = date.Substring(6, 4).ToInt32(),
						Month = date.Substring(0, 2).ToInt32(),
						Day = date.Substring(3, 2).ToInt32()
					};

				case "dd.MM.yyyy":
				case "dd-MM-yyyy":
					return new DateTimeProperties() {
						Year = date.Substring(6, 4).ToInt32(),
						Month = date.Substring(3, 2).ToInt32(),
						Day = date.Substring(0, 2).ToInt32()
					};

				case "yyyy-MM-dd":
					return new DateTimeProperties() {
						Year = date.Substring(0, 4).ToInt32(),
						Month = date.Substring(5, 2).ToInt32(),
						Day = date.Substring(8, 2).ToInt32()
					};

				case "yyyyMMdd":
				default:
					return new DateTimeProperties() {
						Year = date.Substring(0, 4).ToInt32(),
						Month = date.Substring(4, 2).ToInt32(),
						Day = date.Substring(6, 2).ToInt32()
					};
			}
		}
	}

}
